﻿using System;
using System.Collections.Generic;
using System.ServiceModel.Syndication;
using Jacobi.Seesmic.FeedReader.Model.Extensions;

namespace Jacobi.Seesmic.FeedReader.Model
{
    /// <summary>
    /// A specialization of the <see cref="SyndicationItem"/> class to expose extension properties.
    /// </summary>
    public sealed class TimelineFeedItem : SyndicationItem
    {
        private string _uniqueId;

        /// <summary>
        /// Gets the unique Id of the item.
        /// </summary>
        /// <remarks>
        /// This Id must be unique or subsequent items with the same Id will NOT be displayed.
        /// </remarks>
        public string UniqueId
        {
            get
            {
                if (_uniqueId == null)
                {
                    if (Id != null)
                    {
                        _uniqueId = Id;
                    }
                    else
                    {
                        // TODO: retrieve permanent url (guid-tag?)
                        _uniqueId = ContentUrl.AbsoluteUri;
                    }
                }

                return _uniqueId;
            }
        }

        private Uri _contentUrl;

        /// <summary>
        /// Gets the url to the content of the item.
        /// </summary>
        /// <remarks>
        /// First the 'alternate' or 'self' links on the item itself
        /// as well as the links on the feed (parent) are used to
        /// create an absolute url.
        /// </remarks>
        public Uri ContentUrl
        {
            get
            {
                if (_contentUrl == null)
                {
                    SyndicationLink link = null;

                    if (Links.Count > 1)
                    {
                        link = Links.FindAlternateOrSelf();
                    }
                    else if (Links.Count > 0)
                    {
                        link = Links[0];
                    }

                    if (link != null)
                    {
                        _contentUrl = GetAbsoluteUri(this, link);
                    }
                }

                return _contentUrl;
            }
        }

        private Purl11Creator _creatorReader;

        /// <summary>
        /// Gets the feed item creator (when available).
        /// </summary>
        public string Creator
        {
            get
            {
                if (_creatorReader == null)
                {
                    _creatorReader = Purl11Creator.Create(ElementExtensions);
                }

                if (_creatorReader != null)
                {
                    return _creatorReader.Creator;
                }

                return null;
            }
        }

        private IEnumerable<SyndicationLink> _mediaLinks;

        /// <summary>
        /// Gets a collection of media links (Yahoo media content extension).
        /// </summary>
        public IEnumerable<SyndicationLink> MediaLinks
        {
            get
            {
                if (_mediaLinks == null)
                {
                    var links = new List<SyndicationLink>();

                    var content = YahooMediaContent.Create(ElementExtensions);

                    foreach (var mediaContent in content)
                    {
                        var link = new SyndicationLink()
                        {
                            MediaType = mediaContent.Medium,
                            //Title = mediaContent.Title,
                            Uri = new Uri(mediaContent.Url),
                        };

                        links.Add(link);
                    }

                    _mediaLinks = links;
                }

                return _mediaLinks;
            }
        }

        /// <summary>
        /// Helper to build an absolute Uri from the specified <paramref name="link"/>.
        /// </summary>
        /// <param name="feedItem">The <see cref="TimelineFeedItem"/> that owns the <paramref name="link"/>. Must not be null.</param>
        /// <param name="link">Must not be null.</param>
        /// <returns>Returns null when no suitable Uri could be build.</returns>
        private static Uri GetAbsoluteUri(TimelineFeedItem feedItem, SyndicationLink link)
        {
            if (link.Uri.IsAbsoluteUri)
            {
                return link.Uri;
            }
            else
            {
                Uri baseUri = null;

                if (link.BaseUri == null)
                {
                    var siteLink = feedItem.SourceFeed.Links.FindAlternateOrSelf();

                    if (siteLink != null)
                    {
                        if (siteLink.BaseUri == null)
                        {
                            int index = siteLink.Uri.AbsoluteUri.IndexOf(siteLink.Uri.AbsolutePath,
                                StringComparison.OrdinalIgnoreCase);

                            if (index >= 0)
                            {
                                baseUri = new Uri(siteLink.Uri.AbsoluteUri.Substring(0, index));
                            }
                        }
                        else
                        {
                            baseUri = siteLink.BaseUri;
                        }
                    }
                }
                else
                {
                    baseUri = link.BaseUri;
                }

                if (baseUri != null)
                {
                    UriBuilder builder = new UriBuilder(baseUri);
                    builder.Path = link.Uri.OriginalString;

                    return builder.Uri;
                }
            }

            return null;
        }
    }
}